package com.myph.model;


import it.sauronsoftware.base64.Base64;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.Vector;

import android.util.Log;

public class ClientSocket extends Thread {
    public Socket sockobj;
    public Writer writer;
    public Reader reader;

    int sw, points, frequence;
    public Vector res;
    private String[] args;
    private double[] sensorData;
    SocketListener listener = null;
    public void run() {

        try {
            CS();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public ClientSocket(String argsIn[], double[] sensorDataIn) {
        args = argsIn;
        sensorData = sensorDataIn;
    }
    public ClientSocket(String argsIn[], double[] sensorDataIn,SocketListener listenerIn) {
        args = argsIn;
        sensorData = sensorDataIn;
        listener = listenerIn;
    }
    //String args[],double[] sensorData
    void CS() throws UnknownHostException, IOException, InterruptedException {
//		System.out.println(Base64.encode("123"));
//
//		String ss = Base64.encode("123");

//		System.out.println(ss.length());
//		System.out.println(Base64.decode("MTIz"));

        //get those parament
//        System.out.println(args[0] + " " + args[1]);
        
        if(listener != null){
            listener.recordProgress(5);
        }
        String host = args[0];
        int port = Integer.parseInt(args[1]);
        sw = Integer.parseInt(args[2]);
        points = Integer.parseInt(args[3]);
        frequence = Integer.parseInt(args[4]);
        
//        //test para
//        for(int i=0;i<5;++i) {
//            System.out.println("args"+i+args[i]);
//        }
//        sw = 1;
//        points = 7;
//        frequence = 1;
//        host = "192.168.155.3";
//        port = 50002;
        // init
        try {
            sockobj = new Socket(host, port);    
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            Log.d(Util.TAG,"CS"+"exception");
            if(listener != null){
                listener.onError(e);
            }
            return;
        }
        

        if(listener != null){
            listener.recordProgress(10);
        }
        System.out.println("Socket ok!");
        writer = new OutputStreamWriter(sockobj.getOutputStream());
        reader = new InputStreamReader(sockobj.getInputStream());

        commu();

        
        sockobj.close();
        if(listener != null){
            listener.recordProgress(100);
        }

    }

    public String receiveMsg() {
        char readbuf[] = new char[256];
        int readlen;
//		String buf = null;
        StringBuffer sb = new StringBuffer();//init clear
        while (true) {
            try {
                if ((readlen = reader.read(readbuf)) != -1) {
//					System.out.println(readbuf);
                    sb.append(new String(readbuf, 0, readlen));
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                try {
                    reader.close();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    
                    if(listener != null){
                        listener.recordProgress(15);
                        listener.onError(e1);
                    }
                    e1.printStackTrace();
                }
                return null;
            }
            if (sb.length() == 0) {
                continue;
            } else
                break;
        }
        if (sb.length() == 0) return null;
        else return sb.toString();
    }

    /**
     * the process: get test info --> send info about the verification --> get the ACK --> send the command --> get the ACK
     * --> receive the sensor data
     *
     * @throws IOException
     * @throws InterruptedException
     */
    public void commu() throws IOException, InterruptedException {
        ///verfication:get test info
        String buf = receiveMsg();
        if (buf == null) {
            System.out.println("fail to get the verification msg");
            if(listener != null){
                listener.recordProgress(20);
                listener.onError();
                Log.d(Util.TAG,"commu buf == null");
            }
            return;
        }
        Log.d(Util.TAG,"commu receive buf");
        System.out.println("receive:" + buf);
        //send info about the verification
        String data = verifyStr(buf);
        System.out.println("data: " + data);
        if (!sendMsg(data)) {
            System.out.println("fail to send the verification msg");
            if(listener != null){
                listener.recordProgress(30);
                listener.onError();
            }
            return;
        }
        if(listener != null){
            listener.recordProgress(30);
        }
        buf = receiveMsg();
        
        if (buf == null || !buf.equals("ACK")) {
            System.out.println("fail to pass the verification");
            if(listener != null){
                listener.onError();
            }
            return;
        }
        System.out.println("receiving:" + buf);

        //send the command
        //int sw=1,points=7,frequence=2;
        String command = "switch=" + String.valueOf(sw) + "&" + "points=" + String.valueOf(points) + "&" + "frequence=" + String.valueOf(frequence);

        //TODO:check and input from user

        System.out.println("sending command:" + command);

        
        if(listener != null){
            listener.recordProgress(50);
        }
        //send command
        if (!sendMsg(command)) {
            System.out.println("fail to send the command msg");
            if(listener != null){
                listener.onError();
            }
            return;
        }

        if(listener != null){
            listener.recordProgress(70);
        }
        buf = receiveMsg();
        if (!buf.equals("ACK")) {
            System.out.println("Haven't got the ACK from the server!\nFail to send the command");
            if(listener != null){
                listener.onError();
            }
            return;
        }
        if (sw == 0) {
            System.out.println("turn off the sensor");
            if(listener != null){
                listener.onError();
            }
            return;
        }

        System.out.println("receiving sensor data...");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String sttime = sdf.format(new Date());
        SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm:ss");

        res = new Vector<Double>();
        Vector ti = new Vector<String>();
        for (int i = 0; i < points; ++i) {
            Double tp = Double.parseDouble(receiveMsg());
            res.add(tp);
            sensorData[i] = (double) tp;
            ti.add(sdf2.format(new Date()));
            System.out.println(tp + "," + ti.get(i));
            Thread.sleep(frequence * 1000);
            if(listener != null){
                listener.recordProgress(70+30*(i)/points);
            }
        }

        System.out.println("sensorData:" + sensorData[0]);
        reader.close();
        writer.close();
        listener.recordProgress(100);

    }

    private boolean sendMsg(String data) throws IOException {
        try {
            writer.write(data);
        } catch (IOException e) {
            e.printStackTrace();
            writer.close();
            return false;
        }
        try {
            writer.flush();//flush after the writing
        } catch (IOException e) {
            e.printStackTrace();
            writer.close();
            if(listener != null){
//                listener.recordProgress(30);
                listener.onError(e);
            }
            return false;
        }
        return true;
    }

    private String verifyStr(String verStr) {
        String s1 = Base64.encode(verStr);
//		System.out.println("s1:"+s1);
        String salt;
        Random r = new Random();
        char ctemp[] = new char[4];
        for (int i = 0; i < 4; ++i) {
            ctemp[i] = (char) (r.nextInt(26) + 'A');
        }
        salt = new String(ctemp);
        String s2 = salt + s1 + salt;
//		System.out.println("s2:"+s2);
        String s3 = Base64.encode(s2);

//		System.out.println("s3:"+s3);
        return s3;
    }

}
